﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AtomPuzzleSolver.Model;
using System.Threading;
using System.Diagnostics;

namespace AtomPuzzleSolver.View.WinForms
{
    public partial class Form1 : Form
    {
        public List<Label> _Labels = new List<Label>();
        public List<HexagonalGrid> _Grids = new List<HexagonalGrid>();

        public HexagonalGrid grid = new HexagonalGrid(7, 7);
        public Form1()
        {
            InitializeComponent();

            this.ClientSize = new Size(190, 202);


            foreach (var cell in grid.CellsFlat)
            {
                Label l = new Label();
                l.Size = new Size(24, 24);
                l.TextAlign = ContentAlignment.MiddleCenter;
                if (Utilities.IsOdd(cell.Coordinates.X) == 1)
                {
                    l.Location = new Point(5 + cell.Coordinates.X * (l.Size.Width + 2), l.Size.Height / 2 + 5 + cell.Coordinates.Y * (l.Size.Height + 2));
                }
                else
                {
                    l.Location = new Point(5 + cell.Coordinates.X * (l.Size.Width+2), 5 + cell.Coordinates.Y * (l.Size.Height+2));
                }
                l.Text = String.Format("{0},{1}", cell.Coordinates.X, cell.Coordinates.Y);
                l.BackColor = cell.Color;

                this.Controls.Add(l);
                _Labels.Add(l);
            }

            ActivateAtomPuzzle(grid);
            DrawGrid(grid);




            //_Grids = FindSolutions(grid, blue);

            //DrawGrid(_Grids[index]);


            //_Grids = FindSolutions(_Grids[0], red);

            //DrawGrid(_Grids[index]);


//            _Grids = FindSolutions(_Grids[0], yellow);

            //DrawGrid(_Grids[index]);
            //DrawGrid(grid);

            //Molecule m = new Molecule(Color.Yellow);
            //m.AddAtom(0, Direction.SouthEast);
            //m.AddAtom(1, Direction.South);
            //m.AddAtom(2, Direction.SouthEast);
            //m.AddAtom(2, Direction.South);

            //m.Mirror();
            //grid.Insert(m, 3, 0);

            //DrawGrid(grid);

            //grid.Remove(m, 3, 0);

            //DrawGrid(grid, labels);

            //m.Rotate();

            //grid.Insert(m, 3, 0);

            //DrawGrid(grid, labels);

            //Molecule m2 = new Molecule(Color.Orange);
            //m2.AddAtom(0, Direction.SouthEast);
            //m2.AddAtom(1, Direction.South);
            //m2.AddAtom(2, Direction.SouthEast);
            //m2.AddAtom(2, Direction.South);
            //m2.Rotate();
            //m2.Rotate();
            //m2.Rotate();
            //m2.Rotate();

            //grid.Insert(m2, 3, 3);

            //DrawGrid(grid, labels);



            //grid.Insert(m3, 2, 1);

            //DrawGrid(grid, labels);

        }

        public IEnumerable<HexagonalGrid> FindSolutions(HexagonalGrid grid, Molecule molecule)
        {
            //List<HexagonalGrid> results = new List<HexagonalGrid>();
            stopwatch.Start();
            HexagonalGrid originalGrid = grid.Clone();

            foreach (var cell in originalGrid.CellsFlat.Where(c=>c.State==CellState.Active))
            {
                for (int i = 0; i < 2; i++)
                {
                    for (int k = 0; k < 6; k++)
                    {
                        if (grid.Insert(molecule, cell.Coordinates.X, cell.Coordinates.Y))
                        {
                            this.Text = UpdateSpeed();
                            DrawGrid(grid);
                            Application.DoEvents();
                            yield return grid;
                            grid = originalGrid.Clone();
                        }
                        molecule.Rotate();

                    }
                    molecule.Mirror();                    
                }
            }
        }

        DateTime lastUpdate = DateTime.Now;

        static CircularList<double> avgList = new CircularList<double>(10000);
        static Stopwatch stopwatch = new Stopwatch();
        //List<double> avgList = new List<double>();

        private static string UpdateSpeed()
        {
            stopwatch.Stop();

            avgList.Add(1000.0 / (double)stopwatch.ElapsedMilliseconds);
            stopwatch.Reset();
            stopwatch.Start();

            return avgList.Average().ToString();

        }

        private void TryInserting(Molecule m, int i, int j)
        {
            HexagonalGrid grid = new HexagonalGrid(7, 7);
            ActivateAtomPuzzle(grid);

            for (int k = 0; k < 6; k++)
            {
                if (grid.Insert(m, i, j))
                {
                    _Grids.Add(grid);
                    grid = new HexagonalGrid(7, 7);
                    ActivateAtomPuzzle(grid);
                }
                m.Rotate();

            }
        }

        public void DrawGrid(HexagonalGrid grid)
        {
            for (int i = 0; i < grid.CellsFlat.Count; i++)
            {
                _Labels[i].BackColor = grid.CellsFlat[i].Color;
            }
        }

        private void ActivateAtomPuzzle(HexagonalGrid grid)
        {
            grid[0, 2].State = CellState.Active;
            grid[0, 3].State = CellState.Active;
            grid[0, 4].State = CellState.Active;

            grid[1, 1].State = CellState.Active;
            grid[1, 2].State = CellState.Active;
            grid[1, 3].State = CellState.Active;
            grid[1, 4].State = CellState.Active;

            grid[2, 1].State = CellState.Active;
            grid[2, 2].State = CellState.Active;
            grid[2, 3].State = CellState.Active;
            grid[2, 4].State = CellState.Active;
            grid[2, 5].State = CellState.Active;

            grid[3, 0].State = CellState.Active;
            grid[3, 1].State = CellState.Active;
            grid[3, 2].State = CellState.Active;
            grid[3, 3].State = CellState.Active;
            grid[3, 4].State = CellState.Active;
            grid[3, 5].State = CellState.Active;

            grid[4, 1].State = CellState.Active;
            grid[4, 2].State = CellState.Active;
            grid[4, 3].State = CellState.Active;
            grid[4, 4].State = CellState.Active;
            grid[4, 5].State = CellState.Active;

            grid[5, 1].State = CellState.Active;
            grid[5, 2].State = CellState.Active;
            grid[5, 3].State = CellState.Active;
            grid[5, 4].State = CellState.Active;

            grid[6, 2].State = CellState.Active;
            grid[6, 3].State = CellState.Active;
            grid[6, 4].State = CellState.Active;
        }

        private int index = 0;

        private void BackButton_Click(object sender, EventArgs e)
        {
            if (index > 0)
            {
                index--;
                DrawGrid(_Grids[index]);
            }
        }

        private void NextButton_Click(object sender, EventArgs e)
        {
            if (index < _Grids.Count-1)
            {
                index++;
                DrawGrid(_Grids[index]);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Molecule yellow = new Molecule(Color.Yellow);
            yellow.AddAtom(0, Direction.SouthEast);
            yellow.AddAtom(1, Direction.South);
            yellow.AddAtom(2, Direction.SouthEast);
            yellow.AddAtom(2, Direction.South);

            Molecule orange = new Molecule(Color.Orange);
            orange.AddAtom(0, Direction.SouthEast);
            orange.AddAtom(1, Direction.South);
            orange.AddAtom(2, Direction.SouthEast);
            orange.AddAtom(2, Direction.South);

            Molecule blue = new Molecule(Color.Blue);
            blue.AddAtom(0, Direction.SouthEast);
            blue.AddAtom(0, Direction.SouthWest);
            blue.AddAtom(1, Direction.SouthEast);
            blue.AddAtom(2, Direction.SouthWest);

            Molecule purple = new Molecule(Color.Purple);
            purple.AddAtom(0, Direction.SouthEast);
            purple.AddAtom(0, Direction.South);
            purple.AddAtom(0, Direction.SouthWest);
            purple.AddAtom(1, Direction.South);

            Molecule white = new Molecule(Color.White);
            white.AddAtom(0, Direction.SouthEast);
            white.AddAtom(0, Direction.South);
            white.AddAtom(0, Direction.SouthWest);
            white.AddAtom(1, Direction.South);

            Molecule green = new Molecule(Color.Green);
            green.AddAtom(0, Direction.SouthEast);
            green.AddAtom(1, Direction.SouthEast);
            green.AddAtom(1, Direction.South);
            green.AddAtom(2, Direction.South);

            Molecule red = new Molecule(Color.Red);
            red.AddAtom(0, Direction.SouthEast);
            red.AddAtom(0, Direction.South);
            red.AddAtom(2, Direction.South);
            red.AddAtom(3, Direction.South);


            foreach (var item1 in FindSolutions(grid, blue))
            {
                foreach (var item2 in FindSolutions(item1, green))
                {
                    foreach (var item3 in FindSolutions(item2,yellow))
                    {
                        foreach (var item4 in FindSolutions(item3, orange))
                        {
                            foreach (var item5 in FindSolutions(item4, purple))
                            {
                                foreach (var item6 in FindSolutions(item5,white))
                                {
                                    _Grids.Add(item6);
                                    DrawGrid(item6);
                                    Application.DoEvents();
                                    //Thread.Sleep(3000);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
